//
//  InputLayer.m
//  Prism
//
//  Created by Bas du Pre on 25-05-11.
//  Copyright 2011 UU. All rights reserved.
//

#include "global.h"
#if PRISM_OS_IOS
#import "InputLayer.h"
#include "Touch.h"
#include "ios_functions.h"


@implementation InputLayer

@synthesize scene;

-(id) init
{
	// always call "super" init
	// Apple recommends to re-assign "self" with the "super" return value
	if( (self=[super init])) {
		
    }
	return self;
}

- (void)singleTapWithUITouch:(UITouch*)t {
    // SINGLE TAP
    Prism::Touch *touch = [self PrismTouchForUITouch:t];
    PRISM_LOG("Tapped: %@", &touch->touchedNodes);
    
    for (unsigned int i = 0; i < touch->touchedNodes.length(); i++) {
        if (touch->touchedNodes[i]->onTap.hasHandler()) {
            Prism::TouchEventArgs e;
            e.touch = touch;
            touch->touchedNodes[i]->onTap(touch->touchedNodes[i], &e);
            if (e.stop) break;
        }
    }
    
    delete touch;
}

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet *allTouches = [event allTouches];
    
    for (UITouch *touch in allTouches) {
        if ([touch tapCount] == 2) {
            [NSObject cancelPreviousPerformRequestsWithTarget: self];
        } else {
            
        }
    }
        
    Prism::List<Prism::Touch*> pTouches;
    Prism::List<Prism::Node*> touchedNodes;
    for (UITouch *t in allTouches) {
        Prism::Touch *pt = [self PrismTouchForUITouch:t];
        pTouches.pushBack(pt);
        touchedNodes.appendUnique(pt->touchedNodes);
    }
    
    touchedNodes.sort(&Prism::Node::compareByScreenZOrder);
    
    for (unsigned int i = 0; i < touchedNodes.length(); i++) {
        if (touchedNodes[i]->onTouchesBegan.hasHandler()) {
            Prism::TouchesEventArgs e;
            for (unsigned int j = 0; j < pTouches.length(); j++) {
                if (pTouches[j]->touchesNode(touchedNodes[i])) {
                    e.touches.pushBack(pTouches[j]);
                }
            }
            touchedNodes[i]->onTouchesBegan(touchedNodes[i], &e);
            if (e.stop) break;
        }
    }
    
    for (unsigned int i = 0; i < pTouches.length(); i++) {
        delete pTouches[i];
    }
}

- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet *allTouches = [event allTouches];
    
    Prism::List<Prism::Touch*> pTouches;
    Prism::List<Prism::Node*> touchedNodes;
    for (UITouch *t in allTouches) {
        Prism::Touch *pt = [self PrismTouchForUITouch:t];
        pTouches.pushBack(pt);
        touchedNodes.appendUnique(pt->touchedNodes);
    }
    
    touchedNodes.sort(&Prism::Node::compareByScreenZOrder);
    
    for (unsigned int i = 0; i < touchedNodes.length(); i++) {
        if (touchedNodes[i]->onTouchesMoved.hasHandler()) {
            Prism::TouchesEventArgs e;
            for (unsigned int j = 0; j < pTouches.length(); j++) {
                if (pTouches[j]->touchesNode(touchedNodes[i])) {
                    e.touches.pushBack(pTouches[j]);
                }
            }
            touchedNodes[i]->onTouchesMoved(touchedNodes[i], &e);
            if (e.stop) break;
        }
    }
    
    for (unsigned int i = 0; i < pTouches.length(); i++) {
        delete pTouches[i];
    }
}

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet *allTouches = [event allTouches];
    
    for (UITouch *t in touches) {
        if ([t tapCount] == 1) {
            [self performSelector:@selector(singleTapWithUITouch:) withObject:t afterDelay:0.3];
        } else if ([t tapCount] == 2) {
            // DOUBLE TAP
            Prism::Touch *touch = [self PrismTouchForUITouch:t];
            PRISM_LOG("Double tapped: %@", &touch->touchedNodes);
            
            for (unsigned int i = 0; i < touch->touchedNodes.length(); i++) {
                if (touch->touchedNodes[i]->onDoubleTap.hasHandler()) {
                    Prism::TouchEventArgs e;
                    e.touch = touch;
                    touch->touchedNodes[i]->onDoubleTap(touch->touchedNodes[i], &e);
                    if (e.stop) break;
                }
            }
            
            delete touch;
        }
    }
    
    Prism::List<Prism::Touch*> pTouches;
    Prism::List<Prism::Node*> touchedNodes;
    for (UITouch *t in allTouches) {
        Prism::Touch *pt = [self PrismTouchForUITouch:t];
        pTouches.pushBack(pt);
        touchedNodes.appendUnique(pt->touchedNodes);
    }
    
    touchedNodes.sort(&Prism::Node::compareByScreenZOrder);
    
    for (unsigned int i = 0; i < touchedNodes.length(); i++) {
        if (touchedNodes[i]->onTouchesEnded.hasHandler()) {
            Prism::TouchesEventArgs e;
            for (unsigned int j = 0; j < pTouches.length(); j++) {
                if (pTouches[j]->touchesNode(touchedNodes[i])) {
                    e.touches.pushBack(pTouches[j]);
                }
            }
            touchedNodes[i]->onTouchesEnded(touchedNodes[i], &e);
            if (e.stop) break;
        }
    }
    
    for (unsigned int i = 0; i < pTouches.length(); i++) {
        delete pTouches[i];
    }

}

- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [self ccTouchesEnded:touches withEvent:event];
}

- (Prism::Touch*)PrismTouchForUITouch:(UITouch*) t {
    CGPoint cgloc = [t locationInView:[[CCDirector sharedDirector] openGLView]];
    CGPoint cgprevloc = [t previousLocationInView:[[CCDirector sharedDirector] openGLView]];
    
    #if PRISM_AUTOROTATION == PRISM_AUTOROTATION_DIRECTOR
    // When autorotation is handled by the director, iOS thinks the device is 
    // in portrait mode. We have to transform the touch locations. 
    
    cgloc = native_correctPositionCG([[CCDirector sharedDirector] convertToGL: cgloc]);
    cgprevloc = native_correctPositionCG([[CCDirector sharedDirector] convertToGL: cgprevloc]);
    
    #endif
    
    Prism::PointF loc(cgloc.x, cgloc.y);
    Prism::PointF prevloc(cgprevloc.x, cgprevloc.y);
    
    Prism::Touch* touch = new Prism::Touch(loc, prevloc);
    
    touch->tapCount = t.tapCount;
    touch->timestamp = t.timestamp;
    switch (t.phase) {
        case UITouchPhaseBegan:
            touch->phase = Prism::Touch::TouchPhaseBegan;
            break;
        case UITouchPhaseCancelled:
        case UITouchPhaseEnded:
        default:
            touch->phase = Prism::Touch::TouchPhaseEnded;
            break;
        case UITouchPhaseMoved:
            touch->phase = Prism::Touch::TouchPhaseMoved;
            break;
        case UITouchPhaseStationary:
            touch->phase = Prism::Touch::TouchPhaseStationary;
            break;
    }
    
    touch->touchedNodes = scene->hitTest(touch->locationOnScreen());
    
    return touch;
}


@end

#endif